import { isObject, isUndefined, filter, map, merge } from "lodash";
import { getPieDimensions } from "./preparePieData";
import chroma from "chroma-js";

function getAxisTitle(axis) {
  return isObject(axis.title) ? axis.title.text : null;
}

function getAxisScaleType(axis) {
  switch (axis.type) {
    case "datetime":
      return "date";
    case "logarithmic":
      return "log";
    default:
      return axis.type;
  }
}

function darkenColor(color) {
  return chroma(color).darken().hex();
}

function prepareXAxis(axisOptions, additionalOptions, showPortal = false) {
  const axis = {
    title: getAxisTitle(axisOptions),
    color: showPortal ? localStorage.getItem('colorstyle_color') : null,
    gridcolor: showPortal && axisOptions.hasOwnProperty('gridcolor') ? darkenColor(localStorage.getItem('colorstyle_color'), -30) : null,
    type: getAxisScaleType(axisOptions),
    automargin: true,
  };

  if (additionalOptions.sortX && axis.type === "category") {
    if (additionalOptions.reverseX) {
      axis.categoryorder = "category descending";
    } else {
      axis.categoryorder = "category ascending";
    }
  }

  if (!isUndefined(axisOptions.labels)) {
    axis.showticklabels = axisOptions.labels.enabled;
  }

  axis.showline = axisOptions.showLine;
  axis.showgrid = axisOptions.showGrid;

  return merge(axisOptions,axis);
}

function prepareYAxis(axisOptions, showPortal = false) {
  const ayis = {
    title: getAxisTitle(axisOptions),
    color: showPortal ? localStorage.getItem('colorstyle_color') : null,
    gridcolor: showPortal && axisOptions.hasOwnProperty('gridcolor') ? darkenColor(localStorage.getItem('colorstyle_color')) : null,
    type: getAxisScaleType(axisOptions),
    automargin: true,
    autorange: true,
    range: null,
  };
  
  ayis.showline = axisOptions.showLine;
  ayis.showgrid = axisOptions.showGrid;
  ayis.zeroline = axisOptions.zeroLine;
  ayis.showticklabels = axisOptions.showTickLabels;

  return merge(axisOptions, ayis);
}

function preparePieLayout(layout, options, data, showPortal = false) {
  const hasName = /{{\s*@@name\s*}}/.test(options.textFormat);

  const { cellsInRow, cellWidth, cellHeight, xPadding } = getPieDimensions(data);

  if (hasName) {
    layout.annotations = [];
  } else {
    layout.annotations = filter(
      map(data, (series, index) => {
        const xPosition = (index % cellsInRow) * cellWidth;
        const yPosition = Math.floor(index / cellsInRow) * cellHeight;
        return {
          x: xPosition + (cellWidth - xPadding) / 2,
          y: yPosition + cellHeight - 0.015,
          xanchor: "center",
          yanchor: "top",
          text: series.name,
          showarrow: false,
        };
      })
    );
  }

  return layout;
}

function prepareDefaultLayout(layout, options, data, showPortal = false) {
  const y2Series = data.filter(s => s.yaxis === "y2");

  layout.xaxis = prepareXAxis(options.xAxis, options, showPortal);

  layout.yaxis = prepareYAxis(options.yAxis[0], showPortal);
  if (y2Series.length > 0) {
    layout.yaxis2 = prepareYAxis(options.yAxis[1], showPortal);
    layout.yaxis2.overlaying = "y";
    layout.yaxis2.side = "right";
  }

  if (options.series.stacking) {
    layout.barmode = "relative";
  }

  return layout;
}

function prepareBoxLayout(layout, options, data, showPortal = false) {
  layout = prepareDefaultLayout(layout, options, data, showPortal);
  layout.boxmode = "group";
  layout.boxgroupgap = 0.5;

  return layout;
}

export default function prepareLayout(element, options, data, showPortal = false) {
  var bigMargin = false;
  if (options.globalSeriesType === "pie" && options.textposition === "outside") bigMargin = true;

  const layout = {
    margin: bigMargin ? { l: 25, r: 25, b: 50, t: 40, pad: 4 } : { l: 6, r: 6, b: 6, t: 6, pad: 2 },
    // plot size should be at least 5x5px
    width: Math.max(5, Math.floor(element.offsetWidth)),
    height: Math.max(5, Math.floor(element.offsetHeight)),
    autosize: options.autosize || false,
    showlegend: options.legend.enabled,
    legend: {
      traceorder: options.legend.traceorder,
      font: showPortal ? {color: localStorage.getItem('colorstyle_color')} : options.legend.font || null,
    },
    paper_bgcolor: showPortal ? "#00000000" : options.paper_bgcolor || null,
    plot_bgcolor: showPortal ? "#00000000" : options.plot_bgcolor || null,
  };

  switch (options.globalSeriesType) {
    case "pie":
      return preparePieLayout(layout, options, data, showPortal);
    case "box":
      return prepareBoxLayout(layout, options, data, showPortal);
    default:
      return prepareDefaultLayout(layout, options, data, showPortal);
  }
}
